]> git.saurik.com Git - apple/mdnsresponder.git/blob - mDNSMacOS9/Mac OS Test Responder.c
mDNSResponder-567.tar.gz
[apple/mdnsresponder.git] / mDNSMacOS9 / Mac OS Test Responder.c
1 /* -*- Mode: C; tab-width: 4 -*-
2 *
3 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18 #include <stdio.h> // For printf()
19 #include <string.h> // For strlen() etc.
20
21 #include <Events.h> // For WaitNextEvent()
22 #include <SIOUX.h> // For SIOUXHandleOneEvent()
23
24 #include "mDNSEmbeddedAPI.h" // Defines the interface to the client layer above
25
26 #include "mDNSMacOS9.h" // Defines the specific types needed to run mDNS on this platform
27
28 // These don't have to be globals, but their memory does need to remain valid for as
29 // long as the search is going on. They are declared as globals here for simplicity.
30 static mDNS m;
31 static mDNS_PlatformSupport p;
32 static ServiceRecordSet p1, p2, afp, http, njp;
33 static AuthRecord browsedomain1, browsedomain2;
34
35 // This sample code just calls mDNS_RenameAndReregisterService to automatically pick a new
36 // unique name for the service. For a device such as a printer, this may be appropriate.
37 // For a device with a user interface, and a screen, and a keyboard, the appropriate
38 // response may be to prompt the user and ask them to choose a new name for the service.
39 mDNSlocal void Callback(mDNS *const m, ServiceRecordSet *const sr, mStatus result)
40 {
41 switch (result)
42 {
43 case mStatus_NoError: debugf("Callback: %##s Name Registered", sr->RR_SRV.resrec.name->c); break;
44 case mStatus_NameConflict: debugf("Callback: %##s Name Conflict", sr->RR_SRV.resrec.name->c); break;
45 case mStatus_MemFree: debugf("Callback: %##s Memory Free", sr->RR_SRV.resrec.name->c); break;
46 default: debugf("Callback: %##s Unknown Result %d", sr->RR_SRV.resrec.name->c, result); break;
47 }
48
49 if (result == mStatus_NameConflict) mDNS_RenameAndReregisterService(m, sr, mDNSNULL);
50 }
51
52 // RegisterService() is a simple wrapper function which takes C string
53 // parameters, converts them to domainname parameters, and calls mDNS_RegisterService()
54 mDNSlocal void RegisterService(mDNS *m, ServiceRecordSet *recordset,
55 UInt16 PortAsNumber, const char txtinfo[],
56 const domainlabel *const n, const char type[], const char domain[])
57 {
58 domainname t;
59 domainname d;
60 char buffer[MAX_ESCAPED_DOMAIN_NAME];
61 UInt8 txtbuffer[512];
62
63 MakeDomainNameFromDNSNameString(&t, type);
64 MakeDomainNameFromDNSNameString(&d, domain);
65
66 if (txtinfo)
67 {
68 strncpy((char*)txtbuffer+1, txtinfo, sizeof(txtbuffer)-1);
69 txtbuffer[0] = (UInt8)strlen(txtinfo);
70 }
71 else
72 txtbuffer[0] = 0;
73
74 mDNS_RegisterService(m, recordset,
75 n, &t, &d, // Name, type, domain
76 mDNSNULL, mDNSOpaque16fromIntVal(PortAsNumber),
77 txtbuffer, (mDNSu16)(1+txtbuffer[0]), // TXT data, length
78 mDNSNULL, 0, // Subtypes (none)
79 mDNSInterface_Any, // Interface ID
80 Callback, mDNSNULL); // Callback and context
81
82 ConvertDomainNameToCString(recordset->RR_SRV.resrec.name, buffer);
83 printf("Made Service Records for %s\n", buffer);
84 }
85
86 // RegisterFakeServiceForTesting() simulates the effect of services being registered on
87 // dynamically-allocated port numbers. No real service exists on that port -- this is just for testing.
88 mDNSlocal void RegisterFakeServiceForTesting(mDNS *m, ServiceRecordSet *recordset, const char txtinfo[],
89 const char name[], const char type[], const char domain[])
90 {
91 static UInt16 NextPort = 0xF000;
92 domainlabel n;
93 MakeDomainLabelFromLiteralString(&n, name);
94 RegisterService(m, recordset, NextPort++, txtinfo, &n, type, domain);
95 }
96
97 // CreateProxyRegistrationForRealService() checks to see if the given port is currently
98 // in use, and if so, advertises the specified service as present on that port.
99 // This is useful for advertising existing real services (Personal Web Sharing, Personal
100 // File Sharing, etc.) that currently don't register with mDNS Service Discovery themselves.
101 mDNSlocal OSStatus CreateProxyRegistrationForRealService(mDNS *m, UInt16 PortAsNumber, const char txtinfo[],
102 const char *servicetype, ServiceRecordSet *recordset)
103 {
104 InetAddress ia;
105 TBind bindReq;
106 OSStatus err;
107 TEndpointInfo endpointinfo;
108 EndpointRef ep = OTOpenEndpoint(OTCreateConfiguration(kTCPName), 0, &endpointinfo, &err);
109 if (!ep || err) { printf("OTOpenEndpoint (CreateProxyRegistrationForRealService) failed %d", err); return(err); }
110
111 ia.fAddressType = AF_INET;
112 ia.fPort = mDNSOpaque16fromIntVal(PortAsNumber).NotAnInteger;
113 ia.fHost = 0;
114 bindReq.addr.maxlen = sizeof(ia);
115 bindReq.addr.len = sizeof(ia);
116 bindReq.addr.buf = (UInt8*)&ia;
117 bindReq.qlen = 0;
118 err = OTBind(ep, &bindReq, NULL);
119
120 if (err == kOTBadAddressErr)
121 RegisterService(m, recordset, PortAsNumber, txtinfo, &m->nicelabel, servicetype, "local.");
122 else if (err)
123 debugf("OTBind failed %d", err);
124
125 OTCloseProvider(ep);
126 return(noErr);
127 }
128
129 // Done once on startup, and then again every time our address changes
130 mDNSlocal OSStatus mDNSResponderTestSetup(mDNS *m)
131 {
132 char buffer[MAX_ESCAPED_DOMAIN_NAME];
133 mDNSv4Addr ip = m->HostInterfaces->ip.ip.v4;
134
135 ConvertDomainNameToCString(&m->MulticastHostname, buffer);
136 printf("Name %s\n", buffer);
137 printf("IP %d.%d.%d.%d\n", ip.b[0], ip.b[1], ip.b[2], ip.b[3]);
138
139 printf("\n");
140 printf("Registering Service Records\n");
141 // Create example printer discovery records
142 //static ServiceRecordSet p1, p2;
143
144 #define SRSET 0
145 #if SRSET==0
146 RegisterFakeServiceForTesting(m, &p1, "path=/index.html", "Web Server One", "_http._tcp.", "local.");
147 RegisterFakeServiceForTesting(m, &p2, "path=/path.html", "Web Server Two", "_http._tcp.", "local.");
148 #elif SRSET==1
149 RegisterFakeServiceForTesting(m, &p1, "rn=lpq1", "Epson Stylus 900N", "_printer._tcp.", "local.");
150 RegisterFakeServiceForTesting(m, &p2, "rn=lpq2", "HP LaserJet", "_printer._tcp.", "local.");
151 #else
152 RegisterFakeServiceForTesting(m, &p1, "rn=lpq3", "My Printer", "_printer._tcp.", "local.");
153 RegisterFakeServiceForTesting(m, &p2, "lrn=pq4", "My Other Printer", "_printer._tcp.", "local.");
154 #endif
155
156 // If AFP Server is running, register a record for it
157 CreateProxyRegistrationForRealService(m, 548, "", "_afpovertcp._tcp.", &afp);
158
159 // If Web Server is running, register a record for it
160 CreateProxyRegistrationForRealService(m, 80, "", "_http._tcp.", &http);
161
162 // And pretend we always have an NJP server running on port 80 too
163 //RegisterService(m, &njp, 80, "NJP/", &m->nicelabel, "_njp._tcp.", "local.");
164
165 // Advertise that apple.com. is available for browsing
166 mDNS_AdvertiseDomains(m, &browsedomain1, mDNS_DomainTypeBrowse, mDNSInterface_Any, "apple.com.");
167 mDNS_AdvertiseDomains(m, &browsedomain2, mDNS_DomainTypeBrowse, mDNSInterface_Any, "IL 2\\4th Floor.apple.com.");
168
169 return(kOTNoError);
170 }
171
172 // YieldSomeTime() just cooperatively yields some time to other processes running on classic Mac OS
173 mDNSlocal Boolean YieldSomeTime(UInt32 milliseconds)
174 {
175 extern Boolean SIOUXQuitting;
176 EventRecord e;
177 WaitNextEvent(everyEvent, &e, milliseconds / 17, NULL);
178 SIOUXHandleOneEvent(&e);
179 return(SIOUXQuitting);
180 }
181
182 int main()
183 {
184 mStatus err;
185 Boolean DoneSetup = false;
186
187 SIOUXSettings.asktosaveonclose = false;
188 SIOUXSettings.userwindowtitle = "\pMulticast DNS Responder";
189
190 printf("Multicast DNS Responder\n\n");
191 printf("This software reports errors using MacsBug breaks,\n");
192 printf("so if you don't have MacsBug installed your Mac may crash.\n\n");
193 printf("******************************************************************************\n");
194
195 err = InitOpenTransport();
196 if (err) { debugf("InitOpenTransport failed %d", err); return(err); }
197
198 err = mDNS_Init(&m, &p, mDNS_Init_NoCache, mDNS_Init_ZeroCacheSize,
199 mDNS_Init_AdvertiseLocalAddresses, mDNS_Init_NoInitCallback, mDNS_Init_NoInitCallbackContext);
200 if (err) return(err);
201
202 while (!YieldSomeTime(35))
203 {
204 #if MDNS_ONLYSYSTEMTASK
205 // For debugging, use "#define MDNS_ONLYSYSTEMTASK 1" and call mDNSPlatformIdle() periodically.
206 // For shipping code, don't define MDNS_ONLYSYSTEMTASK, and you don't need to call mDNSPlatformIdle()
207 extern void mDNSPlatformIdle(mDNS *const m);
208 mDNSPlatformIdle(&m); // Only needed for debugging version
209 #endif
210 if (m.mDNSPlatformStatus == mStatus_NoError && !DoneSetup)
211 {
212 DoneSetup = true;
213 printf("\nListening for mDNS queries...\n");
214 mDNSResponderTestSetup(&m);
215 }
216 }
217
218 if (p1.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p1);
219 if (p2.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &p2);
220 if (afp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &afp);
221 if (http.RR_SRV.resrec.RecordType) mDNS_DeregisterService(&m, &http);
222 if (njp.RR_SRV.resrec.RecordType ) mDNS_DeregisterService(&m, &njp);
223
224 mDNS_Close(&m);
225
226 return(0);
227 }